﻿Imports ThoughtWorks.CruiseControl.Core
Imports Exortech.NetReflector
Imports System.Data.OleDb

''' <summary>
''' Monitors the database to change between two times. If any changes are found, they are read and returned.
''' </summary>
<ReflectorType("modificationmonitor")>
Public Class ModificationMonitor : Implements ISourceControl

  ''' <summary>
  ''' Monitors the database to change between two times. If any changes are found, they are read and returned.
  ''' </summary>
  ''' <param name="from">information about the last build (in a object)</param>
  ''' <param name="to">information about the actually build (in a object)</param>
  ''' <returns>Modifications</returns>
  Public Function GetModifications([from] As IIntegrationResult, [to] As IIntegrationResult) As Modification() Implements ISourceControl.GetModifications
    Dim modificationList As New List(Of Modification)
    Dim modificationObject As Modification
    Dim dataTable As DataTable

    If ([from] Is Nothing) Then
      Throw New ArgumentNullException("from")
    End If

    If ([to] Is Nothing) Then
      Throw New ArgumentNullException("to")
    End If

    If (String.IsNullOrEmpty(ConnectionString)) Then
      Throw New ConfigurationException("ConnenctionString is null or empty")
    End If

    If (String.IsNullOrEmpty(SqlStatement)) Then
      Throw New ConfigurationException("SqlStatement is null or empty")
    End If

    If (Timeout < 0) Then
      Throw New ConfigurationException("Timeout < 0")
    End If

    Using oleDbCon As New OleDbConnection(ConnectionString)
      oleDbCon.Open()
      Using oleDbCmd As New OleDbCommand(String.Format(SqlStatement, GetFormatedDate([from].StartTime), GetFormatedDate([to].StartTime)), oleDbCon)
        oleDbCmd.CommandTimeout = Timeout

        Using modificationReader = oleDbCmd.ExecuteReader()
          If modificationReader IsNot Nothing Then

            dataTable = modificationReader.GetSchemaTable

            While modificationReader.Read
              modificationObject = New Modification()

              If (GetCheckedRow(dataTable, "type") = True) Then
                modificationObject.Type = CStr(modificationReader("type"))
              End If

              If (GetCheckedRow(dataTable, "user") = True) Then
                modificationObject.UserName = CStr(modificationReader("user"))
              End If

              If (GetCheckedRow(dataTable, "path") = True) Then
                modificationObject.Url = CStr(modificationReader("path"))
              End If

              If (GetCheckedRow(dataTable, "comment") = True) Then
                modificationObject.Comment = CStr(modificationReader("comment"))
              End If

              If (GetCheckedRow(dataTable, "modificationDate") = True) Then
                modificationObject.ModifiedTime = CDate(modificationReader("modificationDate"))
              End If

              If (GetCheckedRow(dataTable, "fileName") = True) Then
                modificationObject.FileName = CStr(modificationReader("fileName"))
              End If

              If (GetCheckedRow(dataTable, "project") = True) Then
                modificationObject.FolderName = CStr(modificationReader("project"))
              End If

              modificationList.Add(modificationObject)
            End While
          End If

        End Using
      End Using
    End Using

    GetModifications = modificationList.ToArray
  End Function

  ''' <summary>
  ''' 
  ''' </summary>
  ''' <param name="dataTable">datatable of rows</param>
  ''' <param name="string">name of a row</param>
  ''' <returns>if the database table contains the row</returns>
  Private Function GetCheckedRow(dataTable As DataTable, [string] As String) As Boolean
    Dim o As Object
    If (Not String.IsNullOrEmpty([string])) Then
      For i As Integer = 0 To dataTable.Rows.Count - 1
        o = dataTable.Rows(i)("ColumnName")
        If (o IsNot Nothing) AndAlso ((CStr(o).ToLower).Equals([string].ToLower)) Then
          Return True
        End If
      Next
    End If
    GetCheckedRow = False
  End Function

  ''' <summary>
  ''' Formate the date; that the sqlstatement can use this.
  ''' </summary>
  ''' <param name="timeToFormate">date from the ccnet</param>
  ''' <returns>Date as String (yyyy-MM-dd HH:mm:ss)</returns>
  Protected Overridable Function GetFormatedDate(timeToFormate As Date) As String
    GetFormatedDate = timeToFormate.ToString("yyyy-MM-dd HH:mm:ss")
  End Function

#Region "Nicht verwendete Interface Methoden"
  ''' <summary>
  ''' Not used
  ''' </summary>
  Public Sub GetSource(result As IIntegrationResult) Implements ISourceControl.GetSource
  End Sub

  ''' <summary>
  ''' Not used
  ''' </summary>
  Public Sub Initialize(project As IProject) Implements ISourceControl.Initialize
  End Sub

  ''' <summary>
  ''' Not used
  ''' </summary>
  Public Sub LabelSourceControl(result As IIntegrationResult) Implements ISourceControl.LabelSourceControl
  End Sub

  ''' <summary>
  ''' Not used
  ''' </summary>
  Public Sub Purge(project As IProject) Implements ISourceControl.Purge
  End Sub
#End Region

#Region "Properties"
  ''' <summary>
  ''' provides the sqlstatement
  ''' </summary>
  ''' <value></value>
  ''' <returns>Sqlstatement</returns>
  ''' <remarks>
  ''' Example: SELECT 'edit' AS [type], 'pma' as [user], 'cocktail' as [path], name as [comment], 'datetime' as [modificationDate] FROM Cocktail WHERE ... {0} ...... CONVERT(datetime,'{1}',120) ....
  ''' Optional: Two placeholders ({0} and {1}), so the plugin knows in which period the changes are to be checked.
  '''</remarks>
  <ReflectorProperty("sqlstatement")>
  Public Overridable Property SqlStatement() As String
  ''' <summary>
  ''' Provides the connectionstring
  ''' </summary>
  ''' <value></value>
  ''' <returns>String to connect with the Database</returns>
  ''' <remarks>Example: Provider=SQLNCLI11.1;Integrated Security=SSPI;Persist Security Info=False;User ID="";Initial Catalog="";Data Source=CLVDOPMA1;Initial File Name="";Server SPN=""</remarks>
  <ReflectorProperty("connectionstring")>
  Public Overridable Property ConnectionString() As String
  ''' <summary>
  ''' Provides the timeout
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks>Example: 5</remarks>
  <ReflectorProperty("timeout")>
  Public Overridable Property Timeout() As Integer
#End Region

End Class